/*********************************************************************************
Organization 					: 				Georgia Institute of Technology
  
Institute 						:				Cognitive Computing Group(CCL)
 
Authors							: 				Santiago Ontanon, Kinshuk Mishra
 												Neha Sugandh 
 												
Class							:				Player
 
Function						: 				Holding the Information corresponding to 
												the Player. Used in the Case base for CBR
****************************************************************************/
package base;

import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;
import java.util.Vector;

import org.jdom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import util.XMLWriter;



public class WargusPlayer implements Serializable {
	private static final long serialVersionUID = 1L;
	int m_ID;
	Integer m_ResourceGold;	// They are "Integer" and not "int" since they can be unknown (null)
	Integer m_ResourceWood;
	Integer m_ResourceOil;
	List<String> m_research;
	Integer m_food;
	Integer m_demand;
	
	Vector<WargusUnit> m_Units;
	
	// This List contains the set of units that the solution of the case makes reference to,
	// but that are not in the game state. It's used by the ADAPTATION module
	// For example, here are units that are created by the solution of the case, but that were not
	// present in the game state.

	Vector<WargusUnit> ReferredUnits = new Vector<WargusUnit>();
		
	public WargusPlayer(int ID,Integer a_ResourceGold, Integer a_ResourceWood, Integer a_ResourceOil, Vector<WargusUnit> a_Units ){
		m_ID = ID;
		m_ResourceGold = a_ResourceGold;
		m_ResourceWood = a_ResourceWood;
		m_ResourceOil = a_ResourceOil;
		m_Units = new Vector<WargusUnit>();
		for(int i=0;i<a_Units.size();i++)
			m_Units.addElement(a_Units.get(i));
		m_food = 0;
		m_demand = 0;
		m_research = new LinkedList<String>();
	}
	
	public WargusPlayer(WargusPlayer a_Player){
		m_ID = a_Player.m_ID;
		this.m_ResourceGold = a_Player.m_ResourceGold;
		this.m_ResourceWood = a_Player.m_ResourceWood;
		this.m_ResourceOil = a_Player.m_ResourceOil;
		m_Units = new Vector<WargusUnit>();
		for(int i=0; i<a_Player.m_Units.size() ;i++)
		{
			this.m_Units.addElement(a_Player.m_Units.get(i));
		}
		
		m_research = new LinkedList<String>();
		for(int i=0; i<a_Player.m_research.size() ;i++)
		{
			this.m_research.add(a_Player.m_research.get(i));
		}
		m_food = a_Player.m_food;
		m_demand = a_Player.m_demand;
	}
	
	
	public Integer getGold(){ return m_ResourceGold;}
	public Integer getWood(){ return m_ResourceWood;}
	public Integer getOil(){return m_ResourceOil;}
	public Vector<WargusUnit> getUnits() {return m_Units;}	
	public List<String> getResearch() {return m_research;}
	public Integer getFood() {return m_food;}
	public Integer getDemand() {return m_demand;}
	
	public void setFood(int food) {m_food = food;}
	public void setDemand(int demand) {m_demand = demand;}

	public void addCompletedReseach(String a_research) {
		m_research.add(a_research);
	}

	public void addReferredUnit(WargusUnit u) {
		ReferredUnits.add(u);
	}
	public Vector<WargusUnit> getReferredUnits(){return ReferredUnits;}		
	
	public static WargusPlayer loadFromXML(Element e) {
		assert e.getName().equals("player") : 
			"WargusPlayer.loadFromXML: Invalid XML Element " + e.getName();
		
		int id = Integer.parseInt(e.getAttributeValue("id"));
		int gold = Integer.parseInt(e.getChildText("resource-gold"));
		int wood = Integer.parseInt(e.getChildText("resource-wood"));
		int oil = Integer.parseInt(e.getChildText("resource-oil"));
		
		Vector<WargusUnit> units = new Vector<WargusUnit>();
		for (Object o : e.getChild("units").getChildren("unit")) {
			Element unitElement = (Element) o;
			units.add(WargusUnit.loadFromXML(unitElement));
		}
		
		return new WargusPlayer(id, gold, wood, oil, units);
	}
	public void writeXML(XMLWriter w) {
		w.tag("player id=\"" + m_ID + "\"");		
		{
			w.tag("resource-gold", m_ResourceGold);
			w.tag("resource-wood", m_ResourceWood);
			w.tag("resource-oil", m_ResourceOil);
			
			w.tag("units");			
			{
				for(WargusUnit u:m_Units) u.writeXML(w);
			}
			w.tag("/units");
		}
		w.tag("/player");
	}	
	
	public int getID() {
		return m_ID;
	}

	public static WargusPlayer ImportXMLPlayer(Node player) {
		int playerID = -1;
		Vector<WargusUnit> Units = new Vector<WargusUnit>();
		int ResourceGold = 0;
		int ResourceWood = 0;
		int ResourceOil = 0;
		int food=0,demand=0;
		WargusPlayer res;
				
		NamedNodeMap att_l=player.getAttributes();
		Node id_n=att_l.getNamedItem("id");
		if (id_n!=null) {
			playerID = Integer.parseInt(id_n.getNodeValue());
		}
	
		Node feature=CBLILRModule.XMLfeatureValue(player, "resource-gold");
		if (feature!=null) ResourceGold = Integer.parseInt(feature.getFirstChild().getNodeValue());
		feature=CBLILRModule.XMLfeatureValue(player, "resource-wood");
		if (feature!=null) ResourceWood = Integer.parseInt(feature.getFirstChild().getNodeValue());
		feature=CBLILRModule.XMLfeatureValue(player, "resource-oil");
		if (feature!=null) ResourceOil = Integer.parseInt(feature.getFirstChild().getNodeValue());
		feature=CBLILRModule.XMLfeatureValue(player, "food");
		if (feature!=null) food = Integer.parseInt(feature.getFirstChild().getNodeValue());
		feature=CBLILRModule.XMLfeatureValue(player, "demand");
		if (feature!=null) demand = Integer.parseInt(feature.getFirstChild().getNodeValue());
		
		Node n_units=CBLILRModule.XMLfeatureValue(player, "units");
		NodeList unit_l= n_units.getChildNodes();										
		int i,l = unit_l.getLength();		
		for(i=0;i<l;i++) {
			Node unit = unit_l.item(i); 
			WargusUnit PU = WargusStateImporter.nodeToUnit(unit);
			if (PU!=null) Units.add(PU);
		}
		
		res = new WargusPlayer(playerID,ResourceGold,ResourceWood,ResourceOil,Units);
		
		res.m_food = food;
		res.m_demand = demand;
		
		Node n_research=CBLILRModule.XMLfeatureValue(player, "research");
		NodeList research_l= n_research.getChildNodes();										
		int i2,l2 = research_l.getLength();		
		for(i2=0;i2<l2;i2++) {
			Node research = unit_l.item(i); 
			String R = research.getFirstChild().getNodeValue();
			if (R!=null) res.m_research.add(R);
		}
		
		return res;
	}
};
